package org.mtmi.ui.controls;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Point;
import org.mtmi.io.IControlIO;
import org.mtmi.io.controls.SliderIO;
import org.mtmi.ui.GraphicUtil;
import org.mtmi.ui.M;
import org.mtmi.ui.controls.edits.SliderControlEditor;
import org.mtmi.ui.edit.IControlEditor;
import org.mtmi.ui.layouts.LayoutData;
import org.mtmi.ui.scenes.COLOR;
import org.mtmi.ui.scenes.Scene;

/**
 * Foreground is center line color,
 * Background is slider background.
 */
public class Slider extends AbstractSlider  implements IOrientable
{

	private static final int thumbRound = 35;
	private static final int round = 40;
	private static final int DEFAULT_WIDTH = 400;
	private static final int DEFAULT_HEIGHT = 66;
	private static final int DEFAULT_THUMB_LENGTH = 75;
		
	private Path outline;
	private Color thumbColor;
	protected int thumbLength;
	protected boolean paintThumbGrip;
	
	public Slider( Scene scene, int flags ) {
		this( scene, false, 0, 0, 100, flags );
	}
	
	public Slider( Scene scene, boolean isHoriz, int valCurrent, int valMin, int valMax, int flags ) {
		super( scene, valCurrent, valMin, valMax, (flags&~M.VERTICAL)|(isHoriz?M.HORIZONTAL:M.VERTICAL) );
		setSize( computeSize(null ) );
		thumbLength = DEFAULT_THUMB_LENGTH;
		thumbColor = COLOR.grey60;
		paintThumbGrip = true;
		setForeground( COLOR.grey10 );
		setBackground( COLOR.grey40 );
	}
	
	@Override
	public Point computeSize(LayoutData l) {
		int w = isHorizontal() ? DEFAULT_WIDTH : DEFAULT_HEIGHT;
		int h = isHorizontal() ? DEFAULT_HEIGHT : DEFAULT_WIDTH;
		return new Point( w, h );
	}

	@Override
	public void paint(GC gc) {
		paintBackground( gc );
		paintSlidingChannel( gc );
		paintThumb( gc );
	}
	
	/** paint slider background */
	protected void paintBackground( GC gc ) {
		gc.setAntialias(SWT.ON);
		gc.setLineWidth( borderWidth );
		gc.setBackground( getBackground() );
		gc.setForeground( COLOR.sceneFg );
		Path path = GraphicUtil.getRoundRectangle(gc, location.x+borderWidth/2, location.y+borderWidth/2, size.x-borderWidth, size.y-borderWidth, round, round);
		gc.fillPath(path);
		gc.drawPath(path);
		path.dispose();
	}
	
	protected void paintSlidingChannel( GC gc ) {
		gc.setForeground( getForeground() );
		gc.setLineCap(SWT.CAP_ROUND);
		gc.setLineWidth(8);
		if( isHorizontal() ) {
			gc.drawLine( location.x+thumbLength/2, location.y+(size.y-4)/2, location.x+size.x-thumbLength/2, location.y+(size.y-4)/2);
		} else {
			gc.drawLine( location.x+1+(size.x-4)/2, location.y+thumbLength/2, location.x+1+(size.x-4)/2, location.y+size.y-thumbLength/2);
		}
	}

	
	protected void paintThumb( GC gc ) {
		int cp = getThumbPosition( getValue() );
		
		if( isHorizontal() ) {
			outline = GraphicUtil.getRoundRectangle(gc, cp, location.y+borderWidth+borderWidth/2, thumbLength, size.y-3*borderWidth, thumbRound, thumbRound);
		} else {
			outline = GraphicUtil.getRoundRectangle(gc, location.x+borderWidth+borderWidth/2, cp, size.x-3*borderWidth, thumbLength, thumbRound, thumbRound);
		}
		gc.setBackground( thumbColor );
		gc.fillPath(outline);
		gc.setForeground( COLOR.grey20 );
		gc.setLineWidth(borderWidth/2);
		gc.drawPath(outline);
		
		if( paintThumbGrip ) {
			if( isHorizontal() ) {
				int yt = location.y+borderWidth*3;
				int yb = location.y+size.y-borderWidth*3;
				int x1 = cp+thumbLength/2;
				int x2 = x1-borderWidth/2;
				gc.setForeground( COLOR.grey20 );
				gc.drawLine( x1, yt, x1, yb );
				gc.setForeground( COLOR.grey70 );
				gc.drawLine( x2, yt, x2, yb );
			} else {
				int xl = location.x+borderWidth*3;
				int xr = location.x+size.x-borderWidth*3;
				int y1  = cp+thumbLength/2;
				int y2  = y1 - borderWidth/2;
				gc.setForeground( COLOR.grey20 );
				gc.drawLine( xl, y1, xr, y1 );
				gc.setForeground( COLOR.grey70 );
				gc.drawLine( xl, y2, xr, y2 );
			}
		}
	}
	
	@Override
	protected boolean isThumbContains( int ex, int ey ) {
		GC gc = new GC( getScene() );
		try {
			return outline!=null && outline.contains( ex, ey, gc, false );
		} finally {
			gc.dispose();
		}
	}
	
	public void setThumbColor( Color c ) {
		thumbColor = c;
	}
	
	public Color getThumbColor() { return thumbColor; }

	@Override
	protected int getPMax() {
		if( isHorizontal() ) {
			return location.x+size.x-borderWidth-thumbLength;
		} else {
			return location.y+borderWidth;
		}
	}
	
	@Override
	protected int getPMin() {
		if( isHorizontal() ) {
			return location.x+borderWidth;
		} else {
			return location.y+size.y-borderWidth-thumbLength;
		}
	}

	@Override
	public Object getAdapter( Class<?> clazz, Object arg ) {
		if( clazz == IControlEditor.class ) {
			return new SliderControlEditor( this );
		}
		if( clazz == IControlIO.class ) {
			return new SliderIO();
		}
		return super.getAdapter( clazz, arg );
	}
	
	@Override
	public void setHorizontal( boolean horizontal ) {
		if( horizontal!=isHorizontal() ) {
			redraw(); //mark old bounds are to be redraw
			
			int w2 = size.x/2;
			int h2 = size.y/2;
			int cx = location.x+w2;
			int cy = location.y+h2;
			
			if( horizontal ) {
				flags &= ~M.VERTICAL; //reset flag
			} else {
				flags |= M.VERTICAL; //set flag
			}
			Point sz = computeSize( new LayoutData(getScene() ) );
			setBounds( cx-sz.x/2, cy-sz.y/2, sz.x, sz.y );
			redraw();
		}
	}
}
